{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# Augmenting Data from Other Data Sources\n",
    "\n",
    "In this notebook, we will use Augmentor to process images that are stored in memory, and are not read locally from a directory on a hard disk.\n",
    "\n",
    "To demonstrate this, we will use Keras to access the MNIST dataset, which is part of the `keras.datasets` module.\n",
    "\n",
    "Note: you can view a tutorial on using Augmentor with your own images, here <https://github.com/mdbloice/Augmentor/blob/master/notebooks/Augmentor_Keras.ipynb> \n",
    "\n",
    "First we make a number of imports:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import Augmentor\n",
    "\n",
    "import keras\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Dropout, Flatten\n",
    "from keras.layers import Conv2D, MaxPooling2D\n",
    "from keras.datasets import mnist\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## Get MNIST Data\n",
    "\n",
    "To get the MNIST digit data, we can just called `load_data()` from the `datasets` module. Keras comes with a number of pre-arranged data sets for testing and experimentation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "(x_train, y_train), (x_test, y_test) = mnist.load_data()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Because we are going to feed the network categorical data, we should convert `y_train` and `y_test`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "y_train = Augmentor.Pipeline.categorical_labels(y_train)\n",
    "y_test = Augmentor.Pipeline.categorical_labels(y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### MNIST Data Format\n",
    "\n",
    "Let's examine the type and shape of the MNIST data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The matrix x_train contains 60000 images, with dimenions of 28 x 28.\n"
     ]
    }
   ],
   "source": [
    "num_images, width, height = np.shape(x_train)\n",
    "print(\"The matrix x_train contains %s images, with dimenions of %s x %s.\" % (num_images, width, height))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "If we take a look at one row of the matrix, let's say at index 0, you will see it contains a single image of shape (28, 28):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(28, 28)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.shape(x_train[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "We can use matplotlib's `imshow` function to render this array as an image:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAADllJREFUeJzt3X+oVXW6x/HPk2lWSlieDtLYPXOH\nCkKYM7WTG2p4nUYcGVAxYoQGL8mcoSYYQ+KGF7r9gJC4zmQUA2eupl3mNt5S0yDmWhKEUFO7sh/a\n7zjiMX8cqZyUcq763D/OcjjZ2d+93Xvtvbbneb/gcPZez1p7PS79uPZea6/1NXcXgHjOKboBAMUg\n/EBQhB8IivADQRF+ICjCDwRF+IGgCD8QFOEHgjq3lSubOHGid3V1tXKVQCh9fX06dOiQ1TJvQ+E3\nszmSVkkaJek/3X1Fav6uri6Vy+VGVgkgoVQq1Txv3W/7zWyUpMck/VTS1ZIWmdnV9b4egNZq5DP/\nVEkfu/un7v43SX+SNC+ftgA0WyPhv0zSniHP+7Np32JmPWZWNrPywMBAA6sDkKemH+139153L7l7\nqaOjo9mrA1CjRsK/V9LkIc+/l00DcBZoJPyvSbrCzL5vZmMk/VzSlnzaAtBsdZ/qc/fjZnaHpP/V\n4Km+Ne6+M7fOADRVQ+f53f05Sc/l1AuAFuLrvUBQhB8IivADQRF+ICjCDwRF+IGgCD8QFOEHgiL8\nQFCEHwiK8ANBEX4gKMIPBEX4gaAIPxAU4QeCIvxAUIQfCIrwA0ERfiAowg8ERfiBoAg/EBThB4Ii\n/EBQhB8IivADQRF+ICjCDwTV0Ci9ZtYn6StJJyQdd/dSHk0hPydPnkzWjx071tT1r1u3rmLt6NGj\nyWV37dqVrD/88MPJ+vLlyyvWHn300eSy559/frK+cuXKZP22225L1ttBQ+HP/LO7H8rhdQC0EG/7\ngaAaDb9L2mpmr5tZTx4NAWiNRt/2T3f3vWZ2qaTnzex9d39p6AzZfwo9knT55Zc3uDoAeWloz+/u\ne7PfByVtkjR1mHl63b3k7qWOjo5GVgcgR3WH38wuNLPxpx5Lmi3p3bwaA9Bcjbzt75S0ycxOvc5/\nu/ufc+kKQNPVHX53/1TSD3PsZcQ6fPhwsn7ixIlk/a233krWt27dWrH25ZdfJpft7e1N1ovU1dWV\nrC9btixZX716dcXaRRddlFx2xowZyfqsWbOS9bMBp/qAoAg/EBThB4Ii/EBQhB8IivADQeVxVV94\n/f39yXp3d3ey/sUXX+TZzlnjnHPS+57UqTqp+mW3S5YsqVi79NJLk8uOGzcuWR8J31Zlzw8ERfiB\noAg/EBThB4Ii/EBQhB8IivADQXGePweXXHJJst7Z2Zmst/N5/tmzZyfr1f7sGzdurFg777zzksvO\nnDkzWUdj2PMDQRF+ICjCDwRF+IGgCD8QFOEHgiL8QFCc589BtevK165dm6w//fTTyfr111+frC9c\nuDBZT5k+fXqyvnnz5mR9zJgxyfr+/fsr1latWpVcFs3Fnh8IivADQRF+ICjCDwRF+IGgCD8QFOEH\ngjJ3T89gtkbSzyQddPcp2bSLJa2X1CWpT9LN7l71ovRSqeTlcrnBlkeeY8eOJevVzqUvX768Yu2h\nhx5KLvviiy8m6zfccEOyjvZSKpVULpetlnlr2fOvlTTntGl3S9rm7ldI2pY9B3AWqRp+d39J0uen\nTZ4naV32eJ2k+Tn3BaDJ6v3M3+nu+7LH+yWl71MFoO00fMDPBw8aVDxwYGY9ZlY2s/LAwECjqwOQ\nk3rDf8DMJklS9vtgpRndvdfdS+5eGgmDGwIjRb3h3yJpcfZ4saT0pV8A2k7V8JvZk5JelnSVmfWb\n2RJJKyT9xMw+knRj9hzAWaTq9fzuvqhC6cc59xJWtfvXVzNhwoS6l33kkUeS9RkzZiTrZjWdUkYb\n4ht+QFCEHwiK8ANBEX4gKMIPBEX4gaC4dfcIsHTp0oq1V199Nbnspk2bkvWdO3cm61OmTEnW0b7Y\n8wNBEX4gKMIPBEX4gaAIPxAU4QeCIvxAUJznHwFSt/bu7e1NLrtt27Zkfd68ecn6/Pnpe7dOmzat\nYm3BggXJZblcuLnY8wNBEX4gKMIPBEX4gaAIPxAU4QeCIvxAUFWH6M4TQ3S3n2rX+8+Zc/oAzd92\n+PDhute9Zs2aZH3hwoXJ+rhx4+pe90iV9xDdAEYgwg8ERfiBoAg/EBThB4Ii/EBQhB8Iqur1/Ga2\nRtLPJB109ynZtHsl/VLSQDbbcnd/rllNonmmTp2arFe7b/+dd96ZrD/11FMVa7feemty2U8++SRZ\nv+uuu5L18ePHJ+vR1bLnXytpuG96/M7du7Mfgg+cZaqG391fkvR5C3oB0EKNfOa/w8zeNrM1ZjYh\n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\nhedBhRoAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fca093de110>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(x_train[0], cmap=\"Greys\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Later, we will pass this entire matrix, containing 60,000 images, to an Augmentor function, which will generate batches of augmented images from this original data."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## Create a Pipeline\n",
    "\n",
    "It is perfectly fine to create a pipeline object without needing to point to a directory on your hard drive. Do this if you want to perform an augmentation task on data from another location, such as from the web or another framework such as Keras."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "p = Augmentor.Pipeline()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "If you then check the pipeline `p`'s status, you will see it has no images or classes associated with it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Operations: 0\n",
      "Images: 0\n",
      "Classes: 0\n",
      "\n",
      "You can remove operations using the appropriate index and the remove_operation(index) function.\n"
     ]
    }
   ],
   "source": [
    "p.status()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Adding operations is done as normal: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Operations: 1\n",
      "\t0: RotateRange (max_right_rotation=5.0 max_left_rotation=-5.0 probability=1 )\n",
      "Images: 0\n",
      "Classes: 0\n",
      "\n",
      "You can remove operations using the appropriate index and the remove_operation(index) function.\n"
     ]
    }
   ],
   "source": [
    "p.rotate(probability=1, max_left_rotation=5, max_right_rotation=5)\n",
    "p.status()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## Design a Neural Network\n",
    "\n",
    "We will use a simple convolutional neural network using Keras to train a model using the augmented MNIST data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "num_classes = 10\n",
    "input_shape = (28, 28, 1)\n",
    "\n",
    "model = Sequential()\n",
    "model.add(Conv2D(32, kernel_size=(3, 3),\n",
    "                 activation='relu',\n",
    "                 input_shape=input_shape))\n",
    "model.add(Conv2D(64, (3, 3), activation='relu'))\n",
    "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(Dropout(0.25))\n",
    "model.add(Flatten())\n",
    "model.add(Dense(128, activation='relu'))\n",
    "model.add(Dropout(0.5))\n",
    "model.add(Dense(num_classes, activation='softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Once a network has been defined, you can compile it so that the model is ready to be trained with data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "model.compile(loss=keras.losses.categorical_crossentropy,\n",
    "              optimizer=keras.optimizers.Adadelta(),\n",
    "              metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Now that the network is ready, we can create a generator using Augmentor, and pass this generator to the neural network created above."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## Create a Generator\n",
    "\n",
    "Now, you can use the MNIST data you gathered earlier and use this to create an generator. The generator will augment the data that you pass to it indefinitely and this can be fed into a neural network in order to train it. In this case we will use the images stored in the matrix `x_train` and their corresponding labels stored in the `y_train` array.\n",
    "\n",
    "We will use the generator later, so we will stored in a variable `g`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128\n",
    "g = p.keras_generator_from_array(x_train, y_train, batch_size=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "We can take a look at what the generator outputs (the generator returns a batch of images and a batch of corresponding labels as a tuple):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "X, y = next(g)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Let's take a look at the ouput of one image, again using index 0 from the batch of images returned by the generator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7fca059a9d90>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAADXlJREFUeJzt3W+MVfWdx/HPB2SUfw9ARoIWl241\nmxCTpZsJ2aSGdNNtI4YE0SiQ2LAJFh/UKEkT/LMP9IkJbrY0xqwkdCXFTdd2k2JEY7Z1ySZas6mO\nhFWp6+oSKhCEIVQLBkXguw/m0Ex17u8O99+5w/f9SiZz7/meM+fLgQ/n3Ps7c3+OCAHIZ0rdDQCo\nB+EHkiL8QFKEH0iK8ANJEX4gKcIPJEX4gaQIP5DUZb3c2bx582LRokW93CWQyoEDB3T8+HFPZN22\nwm/7JkmPS5oq6Z8jYnNp/UWLFml4eLidXQIoGBoamvC6LV/2254q6Z8kLZe0WNJa24tb/XkAequd\n1/xLJb0fEfsj4oykn0la2Zm2AHRbO+G/RtLBMc8PVcv+hO0NtodtD4+MjLSxOwCd1PV3+yNiW0QM\nRcTQ4OBgt3cHYILaCf9hSQvHPP9KtQzAJNBO+F+XdL3tr9oekLRG0q7OtAWg21oe6ouIs7bvkfRL\njQ71bY+IfR3rDEBXtTXOHxEvSnqxQ70A6CFu7wWSIvxAUoQfSIrwA0kRfiApwg8kRfiBpAg/kBTh\nB5Ii/EBShB9IivADSRF+ICnCDyRF+IGkCD+QFOEHkiL8QFKEH0iK8ANJEX4gqZ5O0Q2Mdfbs2bbq\nEVGsT58+/aJ7yoQzP5AU4QeSIvxAUoQfSIrwA0kRfiApwg8k1dY4v+0Dkk5KOifpbEQMdaIpXDo+\n/fTThrUnnniiuO2TTz5ZrF999dXF+quvvlqsZ9eJm3z+JiKOd+DnAOghLvuBpNoNf0j6le03bG/o\nREMAeqPdy/4bI+Kw7askvWT7fyLi5bErVP8pbJCka6+9ts3dAeiUts78EXG4+n5M0rOSlo6zzraI\nGIqIocHBwXZ2B6CDWg6/7Zm2Z194LOk7kt7uVGMAuqudy/75kp61feHn/GtE/HtHugLQdS2HPyL2\nS/rLDvaCSejcuXPF+iuvvNKwtmnTprb23Wyc/8yZMw1rAwMDbe37UsBQH5AU4QeSIvxAUoQfSIrw\nA0kRfiApProbbTl9+nSxfuedd7b8s5sNx1133XVtbZ8dZ34gKcIPJEX4gaQIP5AU4QeSIvxAUoQf\nSIpxfhQ1mwb72LFjxfqsWbNa3nbu3LnF+po1a4p1lHHmB5Ii/EBShB9IivADSRF+ICnCDyRF+IGk\nGOdH0eeff16sP/zww8X6/v37G9Zmz55d3Pb+++8v1pcvX16so4wzP5AU4QeSIvxAUoQfSIrwA0kR\nfiApwg8k1XSc3/Z2SSskHYuIG6plcyX9XNIiSQck3RERv+9em6jLxx9/XKy/8MILxfqUKY3PL4sX\nLy5uu3r16mId7ZnImf8nkm76wrIHJO2OiOsl7a6eA5hEmoY/Il6WdOILi1dK2lE93iHplg73BaDL\nWn3NPz8ijlSPP5Q0v0P9AOiRtt/wi9EPeWv4QW+2N9getj08MjLS7u4AdEir4T9qe4EkVd8bfhJj\nRGyLiKGIGBocHGxxdwA6rdXw75K0rnq8TtJznWkHQK80Db/tZyT9l6S/sH3I9npJmyV92/Z7kv62\neg5gEmk6zh8RaxuUvtXhXlCD8+fPF+t79uwp1j/66KNiffr06Q1rt956a3HbBQsWFOtoD3f4AUkR\nfiApwg8kRfiBpAg/kBThB5Lio7svcc2m2D58+HCxfvvttxfrU6dOLdbnzJnTsHbXXXcVt0V3ceYH\nkiL8QFKEH0iK8ANJEX4gKcIPJEX4gaQY57/E2S7Wm/1K7qlTp4r1ZuP8pbH8uXPnFrdFd3HmB5Ii\n/EBShB9IivADSRF+ICnCDyRF+IGkGOe/xDX7ff1Vq1YV66UptqXmnxewcePGYh314cwPJEX4gaQI\nP5AU4QeSIvxAUoQfSIrwA0k1Hee3vV3SCknHIuKGatkjkr4naaRa7aGIeLFbTaJ1u3btKtYPHjxY\nrJ87d65YX716dbE+c+bMYh31mciZ/yeSbhpn+Y8iYkn1RfCBSaZp+CPiZUknetALgB5q5zX/Pbbf\ntL3dduM5mQD0pVbDv1XS1yQtkXRE0g8brWh7g+1h28MjIyONVgPQYy2FPyKORsS5iDgv6ceSlhbW\n3RYRQxExNDg42GqfADqspfDbXjDm6SpJb3emHQC9MpGhvmckfVPSPNuHJD0s6Zu2l0gKSQck3d3F\nHgF0QdPwR8TacRY/1YVe0KLXXnutYe3BBx8sbttsHH/GjBnF+pYtW4r1gYGBYh314Q4/ICnCDyRF\n+IGkCD+QFOEHkiL8QFJ8dPckcPLkyWL97rsb32bxySefFLdtNtRX+tmSdNVVVxXr6F+c+YGkCD+Q\nFOEHkiL8QFKEH0iK8ANJEX4gKcb5+8Bnn31WrN97773F+rvvvtuwdvbs2eK269evL9Yfe+yxYv2y\ny/gnNFlx5geSIvxAUoQfSIrwA0kRfiApwg8kRfiBpBik7QPPP/98sd5smu3Tp083rC1btqy47aOP\nPlqsT5s2rVivU0S0XJ8yhfMeRwBIivADSRF+ICnCDyRF+IGkCD+QFOEHkmo6zm97oaSnJc2XFJK2\nRcTjtudK+rmkRZIOSLojIn7fvVYnr5GRkWJ906ZNxfqJEyeK9VmzZjWs3XfffcVtr7zyymK9n505\nc6bl+syZM4vbZrgPYCJ/wrOSfhARiyX9taTv214s6QFJuyPiekm7q+cAJomm4Y+IIxGxp3p8UtI7\nkq6RtFLSjmq1HZJu6VaTADrvoq5tbC+S9HVJv5E0PyKOVKUPNfqyAMAkMeHw254l6ReSNkbEH8bW\nYvQm6nFvpLa9wfaw7eFmr30B9M6Ewm97mkaD/9OI2FktPmp7QVVfIOnYeNtGxLaIGIqIocHBwU70\nDKADmobftiU9JemdiNgyprRL0rrq8TpJz3W+PQDdMpFf6f2GpO9Kesv23mrZQ5I2S/o32+sl/U7S\nHd1pcfLbsWNHsd7uy6HNmzc3rK1YsaK47WT+6O3LL7+8rXp2Tf/mI+LXktyg/K3OtgOgVy79OxkA\njIvwA0kRfiApwg8kRfiBpAg/kNTkHeTtI/v27SvWt27dWqyfOnWqWJ8zZ06xfttttzWsDQwMFLdF\nXpz5gaQIP5AU4QeSIvxAUoQfSIrwA0kRfiApxvk7YMaMGcV6aQrtidi5c2exzickoRWc+YGkCD+Q\nFOEHkiL8QFKEH0iK8ANJEX4gKcb5O2D//v3FerOppPfs2VOsL1mypFgfnVcFuDic+YGkCD+QFOEH\nkiL8QFKEH0iK8ANJEX4gqabj/LYXSnpa0nxJIWlbRDxu+xFJ35N0YXL5hyLixW412s+WLVtWrH/w\nwQfF+hVXXFGsM46PbpjITT5nJf0gIvbYni3pDdsvVbUfRcQ/dq89AN3SNPwRcUTSkerxSdvvSLqm\n240B6K6Les1ve5Gkr0v6TbXoHttv2t5ue9w5pWxvsD1se3hkZGS8VQDUYMLhtz1L0i8kbYyIP0ja\nKulrkpZo9Mrgh+NtFxHbImIoIob4rDmgf0wo/LanaTT4P42InZIUEUcj4lxEnJf0Y0lLu9cmgE5r\nGn6PvtX8lKR3ImLLmOULxqy2StLbnW8PQLdM5N3+b0j6rqS3bO+tlj0kaa3tJRod/jsg6e6udDgJ\nTJs2ra06UIeJvNv/a0njDTSnHNMHLhXc4QckRfiBpAg/kBThB5Ii/EBShB9IivADSRF+ICnCDyRF\n+IGkCD+QFOEHkiL8QFKEH0jKEdG7ndkjkn43ZtE8Scd71sDF6dfe+rUvid5a1cne/iwiJvR5eT0N\n/5d2bg9HxFBtDRT0a2/92pdEb62qqzcu+4GkCD+QVN3h31bz/kv6tbd+7Uuit1bV0lutr/kB1Kfu\nMz+AmtQSfts32X7X9vu2H6ijh0ZsH7D9lu29todr7mW77WO23x6zbK7tl2y/V30fd5q0mnp7xPbh\n6tjttX1zTb0ttP2ftn9re5/t+6rltR67Ql+1HLeeX/bbnirpfyV9W9IhSa9LWhsRv+1pIw3YPiBp\nKCJqHxO2vUzSKUlPR8QN1bJ/kHQiIjZX/3HOiYj7+6S3RySdqnvm5mpCmQVjZ5aWdIukv1ONx67Q\n1x2q4bjVceZfKun9iNgfEWck/UzSyhr66HsR8bKkE19YvFLSjurxDo3+4+m5Br31hYg4EhF7qscn\nJV2YWbrWY1foqxZ1hP8aSQfHPD+k/pryOyT9yvYbtjfU3cw45lfTpkvSh5Lm19nMOJrO3NxLX5hZ\num+OXSszXncab/h92Y0R8VeSlkv6fnV525di9DVbPw3XTGjm5l4ZZ2bpP6rz2LU643Wn1RH+w5IW\njnn+lWpZX4iIw9X3Y5KeVf/NPnz0wiSp1fdjNffzR/00c/N4M0urD45dP814XUf4X5d0ve2v2h6Q\ntEbSrhr6+BLbM6s3YmR7pqTvqP9mH94laV31eJ2k52rs5U/0y8zNjWaWVs3Hru9mvI6Inn9Julmj\n7/j/n6S/r6OHBn39uaT/rr721d2bpGc0ehn4uUbfG1kv6UpJuyW9J+k/JM3to97+RdJbkt7UaNAW\n1NTbjRq9pH9T0t7q6+a6j12hr1qOG3f4AUnxhh+QFOEHkiL8QFKEH0iK8ANJEX4gKcIPJEX4gaT+\nHzZ/Mbwa2E0AAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fca05a3ef50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(X[0].reshape(28,28), cmap=\"Greys\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "It's label should also correspond to the image shown above, which we can access using `y`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The image above has the label 1.\n"
     ]
    }
   ],
   "source": [
    "print(\"The image above has the label %s.\" % int(np.nonzero(y[0])[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## Fit the Model using the Generator\n",
    "\n",
    "Now we can fit the model using our generator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "468/468 [==============================] - 6s 12ms/step - loss: 0.7717 - acc: 0.7530\n",
      "Epoch 2/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.3109 - acc: 0.9090\n",
      "Epoch 3/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.2563 - acc: 0.9235\n",
      "Epoch 4/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.2093 - acc: 0.9327\n",
      "Epoch 5/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.1895 - acc: 0.9462\n",
      "Epoch 6/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.1667 - acc: 0.9498\n",
      "Epoch 7/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.1385 - acc: 0.9566\n",
      "Epoch 8/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.1374 - acc: 0.9577\n",
      "Epoch 9/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.1219 - acc: 0.9600\n",
      "Epoch 10/10\n",
      "468/468 [==============================] - 4s 9ms/step - loss: 0.1232 - acc: 0.9615\n"
     ]
    }
   ],
   "source": [
    "h = model.fit_generator(g, steps_per_epoch=len(x_train)/batch_size, epochs=10, verbose=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Summary\n",
    "You can use data loaded into memory rather than reading from disk using Augmentor's `keras_generator_from_array` function. This has the advantage that the online augmentation is much faster than when reading from disk."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
